﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SisVenda.Business;
using SisVenda.Data;
using System.Data;
using System.Collections;
using System.Reflection;
using Froggy.Data;
using SisVenda.Web.messageBox;
using SisVenda.Web.Code;

namespace SisVenda.Web.Restrito.Fn
{
    [System.ComponentModel.DataObject(true)]
    public class CompraFn
    {
        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Select)]
        public DataTable ObterCompraID(int idCompra)
        {
            if (idCompra == 0)
                idCompra = 1;
            #region SQL
            string sql = @"SELECT c.IdCompra, p.CNPJ, p.Nome, c.NumeroPedidonotaFiscal, c.DataCompra, SUM(i.quantidade * i.preco) as Valor
	                            FROM Pessoa p
                                INNER JOIN Fornecedor f
                                    ON p.IdPessoa = f.Pessoa_IdPessoa
                                INNER JOIN Compra c
                                    ON c.Fornecedor_Pessoa_IdPessoa = f.Pessoa_IdPessoa
				                LEFT JOIN ItemCompra i
				                ON i.Compra_idCompra = c.IdCompra
                                WHERE c.IdCompra = @idCompra
                                GROUP BY c.IdCompra, p.CNPJ, p.Nome, c.NumeroPedidonotaFiscal, c.DataCompra";
            #endregion
            DbCommandUtil db = new DbCommandUtil(sql);
            db.AddParameter("@idCompra", DbType.Int32, idCompra);
            return db.GetDataTable();
        }

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Select)]
        public DataTable ObterCompra(string tipoConsulta, string parametroPesquisa)
        {
            string parPes = parametroPesquisa;
            parametroPesquisa = "%" + parPes + "%";
            string sql = null;

            if (tipoConsulta.Equals("Fornecedor"))
            {
                #region SQL
                sql = @"SELECT c.IdCompra, p.Nome, c.NumeroPedidonotaFiscal, c.DataCompra, SUM(i.quantidade * i.preco) as Valor
	                            FROM Pessoa p
                                INNER JOIN Fornecedor f
                                    ON p.IdPessoa = f.Pessoa_IdPessoa
                                INNER JOIN Compra c
                                    ON c.Fornecedor_Pessoa_IdPessoa = f.Pessoa_IdPessoa
				                LEFT JOIN ItemCompra i
				                ON i.Compra_idCompra = c.IdCompra
                                WHERE p.Nome LIKE @parametroPesquisa and p.TipoPessoa = 'J'
                                GROUP BY p.Nome, c.IdCompra, c.NumeroPedidonotaFiscal, c.DataCompra
                                ORDER BY p.Nome";
                #endregion
            }
            else
            {
                #region SQL
                sql = @"SELECT c.IdCompra, p.Nome, c.NumeroPedidonotaFiscal, c.DataCompra, SUM(i.quantidade * i.preco) as Valor
	                            FROM Pessoa p
                                INNER JOIN Fornecedor f
                                    ON p.IdPessoa = f.Pessoa_IdPessoa
                                INNER JOIN Compra c
                                    ON c.Fornecedor_Pessoa_IdPessoa = f.Pessoa_IdPessoa
				                LEFT JOIN ItemCompra i
				                ON i.Compra_idCompra = c.IdCompra
                                WHERE c.NumeroPedidonotaFiscal LIKE @parametroPesquisa 
                                GROUP BY p.Nome, c.IdCompra, c.NumeroPedidonotaFiscal, c.DataCompra
                                ORDER BY p.Nome";
                #endregion

            }
            DbCommandUtil db = new DbCommandUtil(sql);
            db.AddParameter("@parametroPesquisa", DbType.String, parametroPesquisa);
            return db.GetDataTable();
        }

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Select)]
        public DataTable ObterValorTotalCompra(Int32 codigoCompra)
        {
            if (codigoCompra == 0)
                codigoCompra = 1;
            string sql = null;

            #region SQL
            sql = @"SELECT SUM(i.quantidade * i.preco) as Valor
	                            FROM Pessoa p
                                INNER JOIN Fornecedor f
                                    ON p.IdPessoa = f.Pessoa_IdPessoa
                                INNER JOIN Compra c
                                    ON c.Fornecedor_Pessoa_IdPessoa = f.Pessoa_IdPessoa
				                LEFT JOIN ItemCompra i
				                ON i.Compra_idCompra = c.IdCompra
                                WHERE c.IdCompra = @codigoCompra";
            #endregion
            DbCommandUtil db = new DbCommandUtil(sql);
            db.AddParameter("@codigoCompra", DbType.Int32, codigoCompra);
            return db.GetDataTable();
        }

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Select)]
        public DataTable ObterItensCompra(int idCompra)
        {
            #region SQL
            string sql = @"SELECT p.IdProduto, p.Descricao, p.Unidade, i.Quantidade, i.preco, SUM(i.quantidade * i.preco) as Valor
                                FROM Produto p
                                INNER JOIN ItemCompra i
                                    ON p.IdProduto = i.Produto_IdProduto
                                INNER JOIN Compra c
                                    ON c.IdCompra = i.Compra_IdCompra
                                WHERE c.IdCompra = @idCompra 
                                GROUP BY c.IdCompra, p.IdProduto, p.Descricao, p.Unidade, i.Quantidade, i.preco
                                ORDER BY p.Descricao";
            #endregion
            DbCommandUtil db = new DbCommandUtil(sql);
            db.AddParameter("@idCompra", DbType.Int32, idCompra);
            return db.GetDataTable();
        }

        public DataTable RetornarDataTable(IQueryable pObjQuery)
        {
            DataTable _dt = new DataTable();

            //Cria o DataTable
            foreach (var item in pObjQuery)
            {
                Type t = item.GetType();
                PropertyInfo[] properties = t.GetProperties();
                for (int i = 0; i < properties.Length; i++)
                {
                    _dt.Columns.Add(properties[i].Name);
                }
                break;
            }

            IEnumerator en = (IEnumerator)pObjQuery.GetEnumerator();

            //Popula o DataTable
            while (en.MoveNext())
            {
                Type ten = en.Current.GetType();
                PropertyInfo[] propertiesen = ten.GetProperties();
                DataRow _dtrow = _dt.NewRow();
                for (int i = 0; i < propertiesen.Length; i++)
                {
                    object obj = propertiesen[i].GetValue(en.Current, new object[] { });
                    _dtrow[i] = obj;
                }
                _dt.Rows.Add(_dtrow);
            }

            return _dt;
        }


        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Insert)]
        public Int32 InserirCompra(Int32 idFornecedor, Int32 numeroPedidoNotaFiscal, DateTime dataCompra)
        {
            CompraBo compras = new CompraBo();
            Compra compra = new Compra();
            compra.Fornecedor_Pessoa_IdPessoa = idFornecedor;
            compra.NumeroPedidoNotaFiscal = numeroPedidoNotaFiscal;
            compra.DataCompra = dataCompra;
            compras.Add(compra);
            try
            {
                compras.SaveChanges();
                MessageBox.Show("Compra incluida, agora informe os itens da compra... ", MessageBox.MessageType.Success);
                return compra.IdCompra;
            }
            catch
            {
                MessageBox.Show("Erro ao realizar operação!", MessageBox.MessageType.Error);
                return compra.IdCompra;
            }
        }

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Insert)]
        public Int32 InserirItemCompra(Int32 idProduto, Int32 idCompra, Int32 quantidade, decimal preco)
        {
            ItemCompraBo itemCompras = new ItemCompraBo();
            ItemCompra itemCompra = new ItemCompra();
            itemCompra.Produto_IdProduto = idProduto;
            itemCompra.Compra_IdCompra = idCompra;
            itemCompra.Quantidade = quantidade;
            itemCompra.Preco = preco;
            itemCompras.Add(itemCompra);

            IncrementarEstoqueProduto(idProduto, quantidade);

            try
            {
                itemCompras.SaveChanges();
                MessageBox.Show("Item incluido com sucesso!", MessageBox.MessageType.Success);
                return itemCompra.Compra_IdCompra;
            }
            catch
            {
                MessageBox.Show("Erro ao realizar operação!", MessageBox.MessageType.Error);
                return itemCompra.Compra_IdCompra;
            }
        }

        public Boolean IncrementarEstoqueProduto(Int32 idProduto, Int32 estoque)
        {
            ProdutoBo produtos = new ProdutoBo();
            Produto produto = new Produto();

            produto = produtos.Find(pro => pro.IdProduto == idProduto).First<Produto>();

            produto.Estoque = produto.Estoque + estoque;
            produtos.Update(produto);
            try
            {
                produtos.SaveChanges();
                return true;
            }
            catch
            {
                MessageBox.Show("Erro ao adicionar item ao estoque!", MessageBox.MessageType.Error);
                return false;
            }
        }

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Update)]
        public Boolean UpdateCompra(Int32 idCompra, Int32 numeroPedidoNotaFiscal, DateTime dataCompra)
        {
            CompraBo compras = new CompraBo();
            Compra compra = new Compra();

            compra = compras.Find(com => com.IdCompra == idCompra).First<Compra>();

            compra.NumeroPedidoNotaFiscal = numeroPedidoNotaFiscal;
            compra.DataCompra = dataCompra;
            compras.Update(compra);

            try
            {
                compras.SaveChanges();
                MessageBox.Show("Compra alterado com sucesso!", MessageBox.MessageType.Success);
                return true;
            }
            catch
            {
                MessageBox.Show("Erro ao realizar operação!", MessageBox.MessageType.Error);
                return false;
            }
        }

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Update)]
        public Boolean UpdateItemCompra(Int32 idCompra, Int32 idProduto, int quantidade, decimal preco)
        {
            ItemCompraBo itemCompras = new ItemCompraBo();
            ItemCompra itemCompra = new ItemCompra();

            itemCompra = itemCompras.Find(itemCom => itemCom.Compra_IdCompra == idCompra && itemCom.Produto_IdProduto == idProduto).First<ItemCompra>();

            bool sucesso = DecrementarEstoqueProduto(idProduto, (Int32)itemCompra.Quantidade);
            if (sucesso)
            {
                IncrementarEstoqueProduto(idProduto, quantidade);
                itemCompra.Quantidade = quantidade;
            }

            
            itemCompra.Preco = preco;
            itemCompras.Update(itemCompra);
            try
            {
                itemCompras.SaveChanges();
                MessageBox.Show("Item de compra alterado com sucesso!", MessageBox.MessageType.Success);
                return true;
            }
            catch
            {
                MessageBox.Show("Erro ao realizar operação!", MessageBox.MessageType.Error);
                return false;
            }
        }

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Delete)]
        public Boolean DeleteCompra(int idCompra)
        {
            bool sucesso = true;
            CompraBo compras = new CompraBo();
            Compra compra = new Compra();
            ItemCompraBo itemCompras = new ItemCompraBo();
            List<ItemCompra> itemCompra = new List<ItemCompra>();

            itemCompra.AddRange(itemCompras.Find(ic => ic.Compra_IdCompra == idCompra));
            compra = compras.Find(com => com.IdCompra == idCompra).First<Compra>();
            foreach (ItemCompra ic in itemCompra)
            {
                ProdutoBo produtos = new ProdutoBo();
                Produto produto = new Produto();
                
                produto = produtos.Find(pProduto => pProduto.IdProduto == ic.Produto_IdProduto).First<Produto>();
                
                sucesso = EstoquePositivo((Int32)produto.Estoque, (Int32)ic.Quantidade);
                
                if (!sucesso)
                {
                    MessageBox.Show("Operação não permitida!", MessageBox.MessageType.Warning);
                    return false;
                }
            }

            foreach (ItemCompra ic in itemCompra)
            {               
                itemCompras.Delete(ic);
            }

            compras.Delete(compra);
            try
            {
                itemCompras.SaveChanges();
                compras.SaveChanges();
                MessageBox.Show("Compra excluida com sucesso!", MessageBox.MessageType.Success);
                return true;
            }
            catch
            {
                MessageBox.Show("Operação não permitida, há produtos com estoque insuficiente!", MessageBox.MessageType.Warning);
                return false;
            }

        }

        bool EstoquePositivo(Int32  estoque, Int32 quantidade)
        {
            estoque = estoque - quantidade;

            if (estoque >= 0)
                return true;
            else
                return false;
        }

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Delete)]
        public Boolean DeleteItemCompra(Int32 idCompra, Int32 idProduto)
        {
            ItemCompraBo itemCompras = new ItemCompraBo();
            ItemCompra itemCompra = new ItemCompra();

            itemCompra = itemCompras.Find(ic => ic.Compra_IdCompra == idCompra && ic.Produto_IdProduto == idProduto).First<ItemCompra>();

            bool decrementou = DecrementarEstoqueProduto(idProduto, (Int32)itemCompra.Quantidade);

            if (decrementou)
            {
                itemCompras.Delete(itemCompra);
                try
                {
                    itemCompras.SaveChanges();
                    MessageBox.Show("Item de compra excluido com sucesso!", MessageBox.MessageType.Success);
                    return true;
                }
                catch
                {
                    MessageBox.Show("Operação não permitida!", MessageBox.MessageType.Warning);
                    return false;
                }
            }
            else
            {
                MessageBox.Show("Operação não permitida!!", MessageBox.MessageType.Warning);
                return false;
            }
        }

        public Boolean DecrementarEstoqueProduto(Int32 idProduto, Int32 quantidade)
        {
            ProdutoBo produtos = new ProdutoBo();
            Produto produto = new Produto();

            produto = produtos.Find(pro => pro.IdProduto == idProduto).First<Produto>();

            if (produto.Estoque >= quantidade)
            {
                produto.Estoque = produto.Estoque - quantidade;
                produtos.Update(produto);
                try
                {
                    produtos.SaveChanges();
                    return true;
                }
                catch
                {
                    MessageBox.Show("Operação não permitida, estoque de produto insuficiente!", MessageBox.MessageType.Warning);
                    return false;
                }
            }
            else
            {
                MessageBox.Show("Operação não permitida, estoque de produto insuficiente!", MessageBox.MessageType.Warning);
                return false;
            }
        }


        public Int32 obterIdFornecedor(string cnpj)
        {
            Pessoa pessoa = new Pessoa();
            PessoaBo pessoaBo = new PessoaBo();
            try
            {
                pessoa = pessoaBo.Find(pes => pes.CNPJ == cnpj).First<Pessoa>();
                Int32 id = pessoa.IdPessoa;
                pessoaBo = null;
                pessoa = null;
                return id;
            }
            catch
            {
                return -1;
            }

        }

        public string obterNomeFornecedor(string cnpj)
        {
            Pessoa pessoa = new Pessoa();
            PessoaBo pessoaBo = new PessoaBo();
            try
            {
                pessoa = pessoaBo.Find(pes => pes.CNPJ == cnpj).First<Pessoa>();
                string nome = pessoa.Nome;
                pessoaBo = null;
                pessoa = null;
                return nome;
            }
            catch
            {
                return null;
            }

        }

        public DataTable ObterItemCompra(Int32 idProduto, Int32 idCompra)
        {

            #region SQL
            string sql = @"SELECT Quantidade, Preco
	                            FROM ItemCompra
	                            WHERE Produto_IdProduto = @idProduto and Compra_IdCompra = @idCompra";
            #endregion
            DbCommandUtil db = new DbCommandUtil(sql);
            db.AddParameter("@idProduto", DbType.Int32, idProduto);
            db.AddParameter("@idCompra", DbType.Int32, idCompra);
            return db.GetDataTable();
        }

        public DataTable ObterProduto(Int32 idProduto, Int32 idFornecedor)
        {

            #region SQL
            string sql = @"SELECT Descricao, Unidade
	                            FROM Produto AS p
                                INNER JOIN ProdutoFornecedor AS pf 
                                ON (p.IdProduto = pf.Produto_IdProduto)
	                            WHERE p.IdProduto = @idProduto and pf.Fornecedor_Pessoa_IdPessoa = @idFornecedor";
            #endregion
            DbCommandUtil db = new DbCommandUtil(sql);
            db.AddParameter("@idProduto", DbType.Int32, idProduto);
            db.AddParameter("@idFornecedor", DbType.Int32, idFornecedor);
            return db.GetDataTable();
        }

        public string obterCNPJFornecedor(Int32 idFornecedor)
        {
            Pessoa pessoa = new Pessoa();
            PessoaBo pessoaBo = new PessoaBo();
            pessoa = pessoaBo.Find(pes => pes.IdPessoa == idFornecedor).First<Pessoa>();
            string cnpj = pessoa.CNPJ;
            pessoaBo = null;
            pessoa = null;
            return cnpj;
        }
    }
}